
using Abp.Domain.Repositories;
using Abp.EntityFrameworkCore.Repositories;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using SOEI.Solution.DomainEntities.ContractManagement;
using SOEI.Solution.DomainEntities.Parameters;
using SOEI.Solution.DomainEntities.Parameters.DomainService;
using SOEI.Solution.Helper;
using SOEI.Solution.Integratedes.Organization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;


namespace SOEI.Solution.DomainEntities.RegulatoryMange.DomainService
{
    /// <summary>
    /// 领域服务层一个模块的核心业务逻辑
    ///</summary>
    public class AgreementManager : DomainServiceBase, IAgreementManager
    {

        private readonly IRepository<Agreement, string> _agreementRepository;

        private readonly IRepository<ContractSummary, string> _contractSummaryRepository;

        private readonly IRepository<AgreementState, string> _agreementStateRepository;

        private readonly IRepository<RegulatoryAccount, string> _regulatoryAccountRepository;

        private readonly IRepository<Regulator, string> _regulatorRepository;

        private readonly IRepository<SuperviseBank, string> _superviseBankRepository;

        private readonly IRepository<OEconomyOrgani, string> _oEconomyOrganiRepository;

        private readonly IRepository<AgreementChange, string> _agreementChangeRepository;

        private readonly IRepository<AgreementNumber, string> _agreementNumberRepository;

        private readonly IRepository<AgreementBoth, string> _agreementBothRepository;

        private readonly IRepository<ContractBoth, string> _contractBothRepository;

        private readonly IRepository<PropertyCard, string> _propertyCardRepository;

        private readonly IRepository<Located, string> _locatedRepository;

        private readonly IRepository<ViewAgreement, string> _viewAgreementRepository;

        private readonly IParameterManager _parameterManager;


        /// <summary>
        /// 【Agreement】的构造方法
        /// 通过构造函数注册服务到依赖注入容器中
        ///</summary>
        public AgreementManager(
            IRepository<Agreement, string> agreementRepository,
            IRepository<ContractSummary, string> contractSummaryRepository,
            IRepository<RegulatoryAccount, string> regulatoryAccountRepository,
            IRepository<AgreementState, string> agreementStateRepository,
            IRepository<Regulator, string> regulatorRepository,
            IRepository<SuperviseBank, string> superviseBankRepository,
            IRepository<OEconomyOrgani, string> oEconomyOrganiRepository,
            IRepository<AgreementChange, string> agreementChangeRepository,
            IRepository<AgreementNumber, string> agreementNumberRepository,
            IRepository<AgreementBoth, string> agreementBothRepository,
            IRepository<ContractBoth, string> contractBothRepository,
            IRepository<PropertyCard, string> propertyCardRepository,
            IRepository<Located, string> locatedRepository,
            IRepository<ViewAgreement, string> viewAgreementRepository,
            IParameterManager parameterManager
            )
        {
            _agreementRepository = agreementRepository;
            _contractSummaryRepository = contractSummaryRepository;
            _regulatoryAccountRepository = regulatoryAccountRepository;
            _agreementStateRepository = agreementStateRepository;
            _regulatorRepository = regulatorRepository;
            _superviseBankRepository = superviseBankRepository;
            _oEconomyOrganiRepository = oEconomyOrganiRepository;
            _agreementChangeRepository = agreementChangeRepository;
            _agreementNumberRepository = agreementNumberRepository;
            _agreementBothRepository = agreementBothRepository;
            _contractBothRepository = contractBothRepository;
            _propertyCardRepository = propertyCardRepository;
            _locatedRepository = locatedRepository;
            _parameterManager = parameterManager;
            _viewAgreementRepository = viewAgreementRepository;
        }

        #region Join相关

        protected IQueryable<Agreement> QueryJoinAgreemntContract()
        {

            var queryA = _agreementRepository.GetAll().AsNoTracking();
            var queryB = _contractSummaryRepository.GetAll().AsNoTracking();
            var queryC = this._agreementStateRepository.GetAll().AsNoTracking();

            return from a in queryA
                   join b in queryB on a.HTDJH equals b.Id
                   join c in queryC on a.JGXYZTDM equals c.Id into tempC
                   from c in tempC.DefaultIfEmpty()
                   select a.PropVal("contractSummary", b)
                           .PropVal("agreementState", c);
        }

        protected IQueryable<RegulatoryAccount> QueryJoinAccountBank()
        {
            var queryA = _regulatoryAccountRepository.GetAll().AsNoTracking();
            var queryB = _superviseBankRepository.GetAll().AsNoTracking();
            var queryC = _regulatorRepository.GetAll().AsNoTracking();

            return from a in queryA
                   join b in queryB on a.JGYHBH equals b.Id
                   join c in queryC on a.JGBH equals c.Id
                   select a.PropVal("superviseBank", b)
                           .PropVal("regulator", c);
        }

        #endregion


        #region -------------------------------------------------辅助工具生成---------------------------------------------- 

        /// <summary>
        /// 返回列表查询用
        /// </summary>
        /// <returns></returns>
        public IQueryable<ViewAgreement> QueryEntityListAsNoTracking() 
        {
            //var query1 = this.QueryJoinAgreemntContract();
            //var query2 = this.QueryJoinAccountBank();

            //return from a in query1
            //       join b in query2 on a.JGZHDM equals b.Id into tempB
            //       from b in tempB.DefaultIfEmpty()
            //       select a.PropVal("regulatoryAccount", b);

            return _viewAgreementRepository.GetAll().AsNoTracking();

        }

        /// <summary>
        /// 【Agreement】返回表达式数的实体信息即IQueryable类型
        /// </summary>
        /// <returns>IQueryable</returns>
        public IQueryable<Agreement> Query()
        {
            return _agreementRepository.GetAll();
        }
        /// <summary>
        /// 【Agreement】返回即IQueryable类型的实体，不包含EF Core跟踪标记
        /// </summary>
        /// <returns>IQueryable</returns>
        public IQueryable<Agreement> QueryAsNoTracking()
        {
            return _agreementRepository.GetAll().AsNoTracking();
        }
        /// <summary>
        /// 【Agreement】根据Id查询实体信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns>实体</returns>
        public async Task<Agreement> FindByIdAsync(string id)
        {
            var entity = await _agreementRepository.GetAsync(id);
            return entity;
        }
        /// <summary>
        /// 【Agreement】检查实体是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns>bool</returns>
        public async Task<bool> IsExistAsync(string id)
        {
            var result = await _agreementRepository.GetAll().AnyAsync(a => a.Id == id);
            return result;
        }
        /// <summary>
        /// 【Agreement】创建实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<Agreement> CreateAsync(Agreement entity)
        {
            entity.Id = await _agreementRepository.InsertAndGetIdAsync(entity);
            return entity;
        }
        /// <summary>
        /// 【Agreement】更新实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task UpdateAsync(Agreement entity)
        {
            await _agreementRepository.UpdateAsync(entity);
        }
        /// <summary>
        /// 【Agreement】删除实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeleteAsync(string id)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            //await _agreementRepository.DeleteAsync(id);
            var entity = await FindByIdAsync(id);

            if(entity != null)
            {
                entity.JGXYZTDM = "03";

                await UpdateAsync(entity);
            }

            var changes = await _agreementChangeRepository.GetAll().Where(a=> a.JGXYBH == id).ToListAsync();

            foreach (var item in changes)
            {
                item.JGXYZTDM = "03";
                item.BGZT = "03";

                await _agreementChangeRepository.UpdateAsync(item);
            }
        }
        /// <summary>
        /// 【Agreement】批量删除
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task BatchDelete(List<string> input)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            await _agreementRepository.DeleteAsync(a => input.Contains(a.Id));
        }
        #endregion


        #region -------------------------------------------------用户自定义------------------------------------------------
        /*请在此扩展领域服务接口*/

        /// <summary>获取数据库当前时间
        /// </summary>
        /// <returns></returns>
        public DateTime FindSysDate()
        {
            var vDate = (DateTime)_agreementRepository.GetDbContext().Database.ExecuteScalar("SELECT SYSDATE FROM DUAL");

            return vDate;
        }

        /// <summary>获取最新的监管协议编号
        /// </summary>
        /// <returns></returns>
        public string GetAgreementId()
        {
            string vId = _agreementRepository.GetDbContext().Database.ExecuteScalar("SELECT LPAD(SEQ_CLFZJJG_JGXYBH.NEXTVAL, 10, '0') FROM DUAL ") as string;

            return vId;
        }

        /// <summary>获取监管协议变更编号
        /// </summary>
        /// <returns></returns>
        public string GetAgreementChangeId()
        {
            string vId = _agreementChangeRepository.GetDbContext().Database.ExecuteScalar("SELECT LPAD(SEQ_CLFZJJG_JGXYBGBH.NEXTVAL, 10, '0') FROM DUAL") as string;

            return vId;
        }

        /// <summary>获取监管协议号的逻辑
        /// </summary>
        /// <returns></returns>
        public async Task<string> GetAgreementRegId()
        {
            string vSXBH = _agreementNumberRepository.GetDbContext().Database.ExecuteScalar("SELECT TO_CHAR(SYSDATE, 'YY') || TO_CHAR(SYSDATE, 'MM') FROM DUAL") as string;

            int vCount = await _agreementNumberRepository.CountAsync(p => p.Id == vSXBH);

            int vDQSXH;

            AgreementNumber vNumber = null;

            if (vCount == 0)
            {
                vDQSXH = 1;

                await _agreementNumberRepository.InsertAsync(new AgreementNumber()
                {
                    Id = vSXBH,
                    NF = vSXBH.Substring(0, 2),
                    YF = vSXBH.Substring(2, 2),
                    JGXYSXH = vDQSXH,
                    FJGXYSXH = 0
                });

            }
            else
            {
                vDQSXH = await (from a in _agreementNumberRepository.GetAll().AsNoTracking() where a.Id == vSXBH select a.JGXYSXH).FirstOrDefaultAsync();

                vDQSXH++;

                vNumber = await _agreementNumberRepository.FirstOrDefaultAsync(a => a.Id == vSXBH);

                vNumber.JGXYSXH = vDQSXH;

                await _agreementNumberRepository.UpdateAsync(vNumber);
            }

            return string.Format("X-JG{0}{1}", vSXBH, Convert.ToString(vDQSXH).PadLeft(5, '0'));
        }

        /// <summary>获取最新的监管协议双方编号
        /// </summary>
        /// <returns></returns>
        public string GetAgreementBothId()
        {
            string vId = _agreementBothRepository.GetDbContext().Database.ExecuteScalar("SELECT LPAD(SEQ_CLFZJJG_JGXYSFXXBH.NEXTVAL, 10, '0') FROM DUAL") as string;

            return vId;
        }


        /// <summary>获取当前运行的监管机构编号
        /// </summary>
        /// <returns></returns>
        public IQueryable<Regulator> QueryAllRegulator()
        {
            var query = _regulatorRepository.GetAll().AsNoTracking();

            return query.Where(a => a.ZT == "01").OrderBy(a => a.Id);
        }

        /// <summary>查询全部监管账号
        /// </summary>
        /// <returns></returns>
        public IQueryable<RegulatoryAccount> QueryAllRegulatoryAccount()
        {
            var query = this.QueryJoinAccountBank();

            return query.Where(a => a.ZT == "1");
        }

        /// <summary>查询合同
        /// </summary>
        public async Task<ContractSummary> FindContractAsync(Expression<Func<ContractSummary, bool>> predicate)
        {
            var vContract = await _contractSummaryRepository.FirstOrDefaultAsync(predicate);

            if (vContract == null)
            {
                vContract = new ContractSummary();
            }

            vContract.oEconomyOrgani = await _oEconomyOrganiRepository.FirstOrDefaultAsync(a => a.Id == vContract.BrokerageInstitutionId);

            if (vContract.oEconomyOrgani == null)
            {
                vContract.oEconomyOrgani = new OEconomyOrgani();
            }

            vContract.PropertyCard = await _propertyCardRepository.FirstOrDefaultAsync(a => a.Id == vContract.CertificateCode);

            if (vContract.PropertyCard == null)
            {
                vContract.PropertyCard = new PropertyCard();
            }

            vContract.PropertyCard.Located = await _locatedRepository.FirstOrDefaultAsync(a => a.Id == vContract.PropertyCard.ZLBH);

            if (vContract.PropertyCard.Located == null)
            {
                vContract.PropertyCard.Located = new Located();
            }

            var vFwytList = await _parameterManager.QueryUsageOfTheHouse().AsNoTracking().ToListAsync();

            if (vFwytList != null)
            {
                foreach (var item in vFwytList)
                {
                    if (item.Id == vContract.HouseUsage)
                    {
                        vContract.HouseUsageParam = item;
                    }
                }
            }

            if (vContract.HouseUsageParam == null)
            {
                vContract.HouseUsageParam = new Parameter();
            }

            return vContract;
        }
        /// <summary>是否存在已签订的监管协议
        /// </summary>
        public async Task<bool> IsExistTreatyAgreement(string pContractId, string pAgreementId)
        {
            return await _agreementRepository.GetAll().AsNoTracking()
                .AnyAsync(
                    a => "01,02".IndexOf(a.JGLXDM) != -1
                    && "00,01".IndexOf(a.JGXYZTDM) != -1
                    && a.HTDJH == pContractId
                    && (string.IsNullOrWhiteSpace(pAgreementId) || a.Id != pAgreementId)
                );
        }

        /// <summary>是否存在已签订的非监管协议
        /// </summary>
        public async Task<bool> IsExistNoTreatyAgreement(string pContractId, string pAgreementId)
        {
            return await _agreementRepository.GetAll().AsNoTracking()
                .AnyAsync(
                    a => a.JGLXDM == "03"
                      && "00,01".IndexOf(a.JGXYZTDM) != -1
                      && a.HTDJH == pContractId
                      && (string.IsNullOrWhiteSpace(pAgreementId) || a.Id != pAgreementId)
                );
        }

        /// <summary>获取监管协议信息
        /// </summary>
        /// <param name="pAgreementId"></param>
        /// <returns></returns>
        public async Task<Agreement> GetForEditAsync(string pAgreementId)
        {
            var agreement = await FindByIdAsync(pAgreementId);

            if (agreement != null)
            {
                agreement.regulatoryAccount = await QueryJoinAccountBank()
                    .Where(a => a.Id == agreement.JGZHDM)
                    .FirstOrDefaultAsync();

                agreement.contractSummary = await FindContractAsync(a => a.Id == agreement.HTDJH);

                agreement.agreementBoths = await QueryAgreementBoth().Where(a => a.JGXYBH == agreement.Id).OrderBy(a => a.Id).ToListAsync();

            }

            return agreement;
        }

        /// <summary>保存监管协议变更信息
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<AgreementChange> SaveAgreementChange(AgreementChange entity)
        {
            entity.Id = await _agreementChangeRepository.InsertAndGetIdAsync(entity);
            return entity;
        }

        /// <summary>创建协议双方
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<AgreementBoth> CreateAsyncAgreementBoth(AgreementBoth entity)
        {
            entity.Id = await _agreementBothRepository.InsertAndGetIdAsync(entity);

            return entity;
        }

        /// <summary>查询合同双方信息
        /// </summary>
        /// <returns></returns>
        public IQueryable<ContractBoth> QueryContractBoth()
        {
            return _contractBothRepository.GetAll().AsNoTracking();
        }

        /// <summary>查询协议双方信息
        /// </summary>
        /// <returns></returns>
        public IQueryable<AgreementBoth> QueryAgreementBoth()
        {
            return _agreementBothRepository.GetAll().AsNoTracking();
        }

        /// <summary>提交监管协议
        /// </summary>
        public async Task SubmitAgreement(string pId)
        {
            var agreement = await _agreementRepository.GetAsync(pId);

            if (agreement != null)
            {
                //agreement.JGXYZTDM = "01";
                //agreement.YXRQ = FindSysDate();

                agreement.ISJJJGTJ = "1";

                await UpdateAsync(agreement);
            }

            //var changes = await _agreementChangeRepository.GetAll().ToListAsync();

            //foreach (var item in changes)
            //{
            //    item.JGXYZTDM = agreement.JGXYZTDM;
            //    item.YXRQ = agreement.YXRQ;

            //    await _agreementChangeRepository.UpdateAsync(item);
            //}

        }

        public async Task<AgreementChange> UpdateAgreementChange(AgreementChange entity)
        {
            return await _agreementChangeRepository.UpdateAsync(entity);
        }

        public async Task<AgreementChange> GetAgreementChangeAsync(string key)
        {
            return await _agreementChangeRepository.GetAsync(key);
        }

        public async Task<bool> CheckAgreementAny(Expression<Func<Agreement, bool>> expression)
        {
            return await _agreementRepository.GetAll().AsNoTracking().AnyAsync(expression);
        }

        public async Task<AgreementChange> FindAgreementChangeAsync(Expression<Func<AgreementChange, bool>> expression)
        {
            var agreementChange = await _agreementChangeRepository.GetAll().AsNoTracking().Where(expression).OrderBy(a => a.Id).FirstOrDefaultAsync();

            if(agreementChange != null)
            {
                agreementChange.regulatoryAccount = await QueryJoinAccountBank()
                    .Where(a => a.Id == agreementChange.JGZHDM)
                    .FirstOrDefaultAsync();
            }

            return agreementChange;
        }

        /// <summary>提交监管协议变更
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task SubmitAgreementChange(string id)
        {
            var change = await _agreementChangeRepository.GetAsync(id);

            change.SFTJ = "1";

            await _agreementChangeRepository.UpdateAsync(change);
        }

        /// <summary>检查监管协议变更信息
        /// </summary>
        public async Task<bool> CheckAgreementChangeAny(Expression<Func<AgreementChange, bool>> expression)
        {
            return await _agreementChangeRepository.GetAll().AsNoTracking().AnyAsync(expression);
        }

        #endregion

    }
}
